package cn.schoolwow.quickapi.util;

import cn.schoolwow.quickapi.util.domain.JarEntryVisitor;
import cn.schoolwow.quickapi.util.domain.SingleFileVisitor;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ResourceUtil {
    /**查找指定包下的类名*/
    public static Set<String> findClassNameSet(String packageName) throws ClassNotFoundException, IOException {
        String path = packageName.replace('.', '/').replace("\\","/");

        Set<String> classNameSet = new HashSet<>();
        walkDirectoryTree(path, new SingleFileVisitor() {
            @Override
            public void visit(File file, File baseDirectory) throws IOException, ClassNotFoundException {
                String fileName = file.getName();
                if(!fileName.endsWith("Controller.java")&&!fileName.endsWith("Controller.class")){
                    return;
                }

                String filePath = file.getAbsolutePath().replace("\\","/");
                String className = filePath.replace(path, "").substring(1);
                className = className.substring(0,className.lastIndexOf(".")).replace('/','.');
                classNameSet.add(className);
            }
        }, new JarEntryVisitor() {
            @Override
            public void visit(JarURLConnection jarURLConnection, JarFile jarFile, JarEntry jarEntry, URL url) throws IOException, ClassNotFoundException {
                String jarEntryName = jarEntry.getName();
                if(!jarEntryName.endsWith("Controller.java")&&!jarEntryName.endsWith("Controller.class")) {
                    return;
                }
                String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                classNameSet.add(className);
            }
        });
        return classNameSet;
    }

    /**
     * 便利指定路径
     * */
    public static void walkDirectoryTree(String path, SingleFileVisitor singleFileVisitor, JarEntryVisitor jarEntryVisitor) throws IOException, ClassNotFoundException {
        File file = new File(path);
        URL url = file.toURI().toURL();
        if(!file.exists()){
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            url = classLoader.getResource(path);
        }

        if (url == null) {
            throw new IllegalArgumentException("路径不存在!路径:"+path);
        }
        switch (url.getProtocol()) {
            case "file": {
                File baseDirectory = new File(url.getFile());
                if (!baseDirectory.isDirectory()) {
                    throw new IllegalArgumentException("文件路径不是文件夹!路径" + path);
                }
                Files.walkFileTree(baseDirectory.toPath(), new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                        File f = file.toFile();
                        try {
                            singleFileVisitor.visit(f, baseDirectory);
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                        return FileVisitResult.CONTINUE;
                    }
                });
            }break;
            case "jar": {
                JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                if(null==jarURLConnection){
                    return;
                }
                JarFile jarFile = jarURLConnection.getJarFile();
                if(null==jarFile){
                    return;
                }
                Enumeration<JarEntry> jarEntries = jarFile.entries();
                while (jarEntries.hasMoreElements()) {
                    JarEntry jarEntry = jarEntries.nextElement();
                    jarEntryVisitor.visit(jarURLConnection, jarFile, jarEntry, url);
                }
            }
        }
    }

}
